package net.maku.project.job;

import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.maku.project.entity.ProcessStatesEntity;
import net.maku.project.service.InfoService;
import net.maku.project.service.ProcessStatesService;
import net.maku.project.service.ProcessStepsService;
import net.maku.project.vo.InfoVO;
import net.maku.sms.service.SmsService;
import net.maku.system.entity.SysRoleEntity;
import net.maku.system.service.SysRoleService;
import net.maku.system.service.SysUserService;
import org.springframework.stereotype.Service;
import java.time.temporal.ChronoUnit;
import java.time.*;
import java.util.*;

/**
 * @FileName: ProcessDeadlineChecker
 * @Project: maku-boot-zzhl
 * @Package: net.maku.project.job
 * @Author: Aili
 * @Date: 2024/7/16 22:22
 * @Version: 1.0.0
 * @Description: ProcessDeadlineChecker Description
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProcessDeadlineChecker {
    private final ProcessStatesService processStatesService;
    private final ProcessStepsService processStepsService;
    private final InfoService infoService;
    private final SysRoleService sysRoleService;
    private final SmsService smsService;


    /**
     * 定时任务
     */
    public void run(String params) throws InterruptedException {
        /*短信模板
        * String.format("【疏附县招商慧链项目管理平台】\n现有%s公司（个人）已于%s日前向%s单位提报%s项目资料，用于办理%s手续，截止目前仍未办结，逾期%s日，请您予以协调处理！\n企业（个人）联系方式:%s，电话号码:%s",
                    params.get("companyName"), params.get("days"), params.get("department"), params.get("projectName"), params.get("procedure"), params.get("overdueDays"), params.get("contact"), params.get("contactMobile"));
        * */
        List<ProcessStatesEntity> inProgressStates = processStatesService.getInProgressStates();

        // 遍历每一个进行中的流程状态
        inProgressStates.forEach(state -> {
            if (state.getTimerStarted() == 1 && state.getStartTime() != null) {
                // 计算逾期天数
                long overdueDays = calculateOverdueDays(state.getStartTime(), state.getStepId());

                // 只有当逾期天数超过环节的办结时限加上额外的三天宽限期时，才发送逾期通知
                if (overdueDays > 3) { // 注意：这里直接比较逾期天数是否超过3天，因为calculateOverdueDays方法已经处理了办结时限的逻辑
                    sendOverdueNotification(state);
                }
            }
        });
        log.info("我是定时任务，我在被执行");
    }

    private long calculateOverdueDays(LocalDateTime startTime, Long stepId) {
        // 根据stepId查询环节的办结时限
        Long deadline = Long.parseLong(processStepsService.getDeadLine(stepId));

        // 如果办结时限为0，表示不限时长，直接返回0表示不逾期
        if (deadline == 0) {
            return 0;
        }

        // 计算逾期天数，需要考虑工作日
        // 将LocalDateTime转换为LocalDate，因为我们只关心日期部分
        LocalDate startDate = startTime.toLocalDate();
        LocalDate endDate = LocalDate.now();

        // 初始化工作日计数器
        Long workDays = 0L;

        // 循环遍历从开始日期到结束日期的所有日期
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            // 检查当前日期是否为工作日（周一至周五）
            if (isWorkday(date)) {
                workDays++;
            }
        }

        // 返回逾期天数，即实际经过的工作日数减去环节的办结时限
        return workDays - deadline;
    }

    // 辅助方法：检查给定日期是否为工作日
    private boolean isWorkday(LocalDate date) {
        DayOfWeek dayOfWeek = date.getDayOfWeek();
        return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;
    }

    private void sendOverdueNotification(ProcessStatesEntity state) {

        InfoVO infoVO = infoService.getInfoById(state.getProjectId());

        Map<String, String> params = new HashMap<>();
        params.put("companyName", infoVO.getInvestorName());
        params.put("projectName", infoVO.getProjectName());
        params.put("procedure", processStepsService.getNameById(state.getStepId()));
        //这里days是指已于X日前报送资料，days=X;X=(今天-开始时间)
        // 计算报送资料的天数
        LocalDate startDate = state.getStartTime().toLocalDate();
        LocalDate endDate = LocalDate.now();

        long totalDays = ChronoUnit.DAYS.between(startDate, endDate);

        params.put("days", String.valueOf(totalDays));
        //这里overdueDays是指逾期X天，指逾期天数，overdueDays=X;X=(今天-开始时间)工作日-办结时限
        // 计算逾期天数，需要考虑工作日
        Long overdueDays = calculateOverdueDays(state.getStartTime(), state.getStepId());
        params.put("overdueDays", overdueDays + "个工作");

        params.put("contact", infoVO.getContactName());
        params.put("contactMobile", infoVO.getContactPhone());

        // 获取当前处理者的所有角色
        List<SysRoleEntity> roles = sysRoleService.getRoleByIds(state.getCurrentHandler());
//        // 使用Set收集所有"SFX_LEADER"角色的ID，自动去除重复
//        Set<Long> leaderRoleIdsSet = roles.stream()
//                .filter(role -> "SFX_LEADER".equals(role.getRoleCode()))
//                .map(SysRoleEntity::getId)
//                .collect(Collectors.toSet());



// 将Set转换为List，以便放入参数map中     WeeklyProgressAlerts
//        List<Long> leaderRoleIds = new ArrayList<>(leaderRoleIdsSet);

// 查找第一个非领导角色的部门名称
        String department = roles.stream()
                .filter(role -> !role.getRoleCode().endsWith("_LEADER"))
                .map(SysRoleEntity::getName)
                .findFirst()
                .orElse("");

        params.put("department", department);
        params.put("templateId", "D");
        String mobile = infoVO.getLinkedLeaderPhone();
        // 获取当前处理者的所有手机号
//        List<String> mobiles = sysUserService.getUserMobilesByRoleIds(leaderRoleIds);
        //遍历mobiles，发送短信
//        for (String mobile : mobiles) {
//            // 发送短信
//            if (StrUtil.isNotBlank(mobile)) {
//                if (mobile.length() != 11||!mobile.matches("^1[3456789]\\d{9}$")) {
//                    log.error("手机号错误，手机号为：" + mobile);
//                }else {
//                    smsService.send(mobile, params);
//                }
//            }
//        }
        // 发送短信
            if (StrUtil.isNotBlank(mobile)) {
                if (mobile.length() != 11||!mobile.matches("^1[3456789]\\d{9}$")) {
                    log.error("手机号错误，手机号为：" + mobile);
                }else {
                    smsService.send(mobile, params);
                }
    }
}}
